# -*- coding: utf-8 -*-

import logging
from odoo import api, fields, models, tools

_logger = logging.getLogger(__name__)

class PriceHistory(models.Model):
    """
    Odoo 模型以 Python 类的形式展现，继承 models.Model类，创建了新 Odoo 模型：library.book。
    Odoo的模型保存在中央注册表(central registry)中，可通过 env 环境对象(老 API 中称为 pool)获取。
    它是一个数据库保存所有可用模型类引用的字典，其中的词条可通过模型名引用 。
    具体来说，模型方法中的代码可使用self.env[‘library.book’]来获取表示 library.book模型的模型类。

    在前述代码中以及在大多数据 Odoo 模型中的类会继承models.Model类。
    这类模型在数据库中持久化存储：会为模型创建数据表并存储记录直至删除。
    但 Odoo 中还有另外两种模型类型：临时模型和抽象模型。

    在前述代码中以及在大多数据 Odoo 模型中的类会继承models.Model类。这类模型在数据库中持久化存储：会为模型创建数据表并存储记录直至删除。
    但 Odoo 中还有另外两种模型类型：临时模型和抽象模型。

    临时模型继承models.TransientModel类，用于向导式的用户交互。这类数据会存储在数据库中，但仅是临时性的。会定时运行清空 job 来清除这些表中的老数据。
    比如Settings > Translations菜单下的Load a Language对话窗口，就使用了临时模型来存储用户选择并实现向导逻辑。

    抽象模型继承models.AbstractModel类，它不带有数据存储。抽象模型用作可复用的功能集，与使用 Odoo 继承功能的其它模型配合使用。
    例如mail.thread是 Discuss 应用中的一个抽象模型，用于为其它模型添加消息和follower 功能。
    """
    # _name = "purchase.price_report"
    _inherit = "purchase.report"
    _description = "Price History"
    _auto = False
    _order = 'date_order desc, price_total desc'
    # _order设置浏览模型记录时或列表视图的默认排序。
    # 其值为 SQL 语句中 order by 使用的字符串，所以可以传入符合 SQL 语法的任意值，它有智能模式并支持可翻译及many-to-one字段名。

    @api.model_cr
    def init(self):
        _logger.debug("execute init for purchase_report")
        # self._table = sale_report
        tools.drop_view_if_exists(self.env.cr, self._table)
        # CREATE or REPLACE VIEW self._table as ( self._select() FROM (self._from()) self._group_by())
        self.env.cr.execute("""CREATE or REPLACE VIEW %s as (
            %s
            FROM ( %s )
            %s
            )""" % (self._table, self._newselect(), self._from(), self._group_by()))

    def _newselect(self):
        """
        :COALESCE
            返回列表中的第一个非空表达式
        :NULLIF
            相等返回为空
        :decimal(精确数值)
            decimal不存在精度损失，数据类型decimal(p,s) 需要分别指定小数的最大位数（p）和小数位的数量（s）：
            p (precision) ：指定小数的最大位数，小数点的左侧和右侧的数字的总数量不能超过p，p的取值范围是从1到38，默认值为18。
            s (scale)：指定在小数点右侧的小数位数，p-s是小数点左边的最大位数。s必须是从0到p的值，只有在指定了精度的情况下才能指定s，s的默认值是0，因此，0 <= s <= p。
        : '::'（eg: sum(XX)::decimal(16,2)）
            PostgreSQL符号，在这种情况下::将sum(XX)转换为decimal(16,2)类型
        :currency_rate.rate
            因以人民币为基准，而purchase_report 默认是以英镑为基准进行绘制图表，所以去除currency_rate.rate
        :return:
        """
        select_str = """
            WITH currency_rate as (%s)
                SELECT
                    min(l.id) as id,
                    s.date_order as date_order,
                    s.state,
                    s.date_approve,
                    s.dest_address_id,
                    s.partner_id as partner_id,
                    s.user_id as user_id,
                    s.company_id as company_id,
                    s.fiscal_position_id as fiscal_position_id,
                    l.product_id,
                    p.product_tmpl_id,
                    t.categ_id as category_id,
                    s.currency_id,
                    t.uom_id as product_uom,
                    sum(l.product_qty/u.factor*u2.factor) as unit_quantity,
                    extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
                    extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
                    count(*) as nbr_lines,
                    sum(l.price_unit * l.product_qty)::decimal(16,2) as price_total,
                    sum(l.product_qty * l.price_unit)/NULLIF(sum(l.product_qty/u.factor*u2.factor),0.0)::decimal(16,2) as negociation,
                    sum(ip.value_float*l.product_qty/u.factor*u2.factor)::decimal(16,2) as price_standard,
                    (sum(l.product_qty * l.price_unit)/NULLIF(sum(l.product_qty/u.factor*u2.factor),0.0))::decimal(16,2) as price_average,
                    partner.country_id as country_id,
                    partner.commercial_partner_id as commercial_partner_id,
                    analytic_account.id as account_analytic_id,
                    sum(p.weight * l.product_qty/u.factor*u2.factor) as weight,
                    sum(p.volume * l.product_qty/u.factor*u2.factor) as volume
        """ % self.env['res.currency']._select_companies_rates()
        return select_str

